package com.rxh.service.impl;

import com.rxh.mapper.base.IdMapper;
import com.rxh.mapper.core.*;
import com.rxh.pojo.base.SearchInfo;
import com.rxh.pojo.core.CoreAcquirer;
import com.rxh.pojo.core.CoreAcquirerAccount;
import com.rxh.pojo.core.CoreAcquirerRate;
import com.rxh.pojo.core.CoreBank;
import com.rxh.service.AcquirerService;
import com.rxh.utils.SystemConstant;
import com.rxh.utils.UUID;
import com.rxh.vo.VoCoreAcquirer;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * User: 陈俊雄
 * Date: 2018/3/22
 * Time: 15:09
 * Project: Management
 * Package: com.rxh.service.impl
 */
@Service
public class AcquirerServiceImpl implements AcquirerService {
    @Resource
    private CoreAcquirerMapper acquirerMapper;
    @Resource
    private CoreAcquirerAccountMapper acquirerAccountMapper;
    @Resource
    private CoreBankMapper bankMapper;
    @Resource
    private CoreAcquirerRateMapper acquirerRateMapper;
    @Resource
    private CoreOrderMapper orderMapper;
    @Resource
    private IdMapper idMapper;

    @Cacheable(value = "core_bank", key = "'core_bank'")
    @Override
    public List<CoreBank> selectAllBank() {
        return bankMapper.selectAll();
    }

    @CacheEvict(value = "core_bank", key = "'core_bank'", condition = "#result == true")
    @Override
    public Boolean updateBank(CoreBank bank, String userName) {
        bank.setModifier(userName);
        bank.setModifyTime(new Date());
        return bankMapper.updateByPrimaryKeySelective(bank) == 1;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_bank", key = "'core_bank'", condition = "#result.size() != #idList.size()")
    })
    @Override
    public List<Integer> deleteBank(List<Integer> idList) {
        List<Integer> undeletable = new ArrayList<>();
        idList.forEach(aLong -> {
            List<CoreAcquirer> acquirerList = selectAllAcquirer()
                    .stream()
                    .filter(acquirer -> acquirer.getBankId().equals(aLong))
                    .collect(Collectors.toList());
            if (acquirerList.size() == 0) {
                bankMapper.deleteByPrimaryKey(aLong);
            } else {
                undeletable.add(aLong);
            }
        });
        return undeletable;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_bank", key = "'core_bank'", condition = "#result == true")
    })
    @Override
    public Boolean addBank(CoreBank bank, String userName) {
        bank.setCreator(userName);
        bank.setCreateTime(new Date());
        bank.setId(UUID.createIntegerKey(idMapper.selectLastId("core_bank")));
        return bankMapper.insertSelective(bank) == 1;
    }

    @Cacheable(value = "core_acquirer", key = "'core_acquirer'")
    @Override
    public List<CoreAcquirer> selectAllAcquirer() {
        return acquirerMapper.selectAll();
    }

    @Override
    public List<CoreAcquirer> selectAllEnableAcquirer() {
        return selectAllAcquirer()
                .stream()
                .filter(acquirer -> acquirer.getStatus().equals(SystemConstant.ENABLE))
                .collect(Collectors.toList());
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer", key = "'core_acquirer'", condition = "#result == true"),
            @CacheEvict(value = "core_acquirer_rate", key = "'core_acquirer_rate:' + #acquirer.id", condition = "#result == true")
    })
    @Override
    public Boolean updateAcquirer(VoCoreAcquirer acquirer, String userName) {
        Date date = new Date();
        acquirer.setModifier(userName);
        acquirer.setModifyTime(date);
        if (acquirer.getAcquirerRates() != null) {
            for (CoreAcquirerRate car :
                    acquirer.getAcquirerRates()) {
                if (car.getId() == null) {
                    car.setAcquirerId(acquirer.getId());
                    car.setId(UUID.createIntegerKey(idMapper.selectLastId("core_acquirer_rate")));
                    car.setCreator(userName);
                    car.setCreator(userName);
                    car.setCreateTime(date);
                    addAcquirerRate(car);
                } else {
                    car.setModifier(userName);
                    car.setModifyTime(date);
                    updateAcquirerRateById(car);
                }
            }
        }
        return acquirerMapper.updateByPrimaryKeySelective(acquirer) == 1;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer", key = "'core_acquirer'", condition = "#result.size() != #idList.size()"),
            @CacheEvict(value = "core_acquirer_rate", allEntries = true, condition = "#result.size() != #idList.size()")
    })
    @Override
    public List<Integer> deleteAcquirer(List<Integer> idList) {
        List<Integer> undeletable = new ArrayList<>();
        idList.forEach(aLong -> {
            List<CoreAcquirerAccount> accountList = selectAllAcquirerAccount()
                    .stream()
                    .filter(acquirerAccount -> acquirerAccount.getAcquirerId().equals(aLong))
                    .collect(Collectors.toList());
            if (accountList.size() == 0) {
                acquirerMapper.deleteByPrimaryKey(aLong);
                deleteAcquirerRateByAcquirerId(aLong);
            } else {
                undeletable.add(aLong);
            }
        });
        return undeletable;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer", key = "'core_acquirer'", condition = "#result == true")
    })
    @Override
    public Boolean addAcquirer(VoCoreAcquirer acquirer, String userName) {
        Date date = new Date();
        acquirer.setCreator(userName);
        acquirer.setCreateTime(date);
        acquirer.setId(UUID.createIntegerKey(idMapper.selectLastId("core_acquirer")));
        for (CoreAcquirerRate car :
                acquirer.getAcquirerRates()) {
            car.setAcquirerId(acquirer.getId());
            car.setId(UUID.createIntegerKey(idMapper.selectLastId("core_acquirer_rate")));
            car.setCreator(userName);
            car.setCreateTime(date);
            addAcquirerRate(car);
        }
        return acquirerMapper.insertSelective(acquirer) == 1;
    }

    @Cacheable(value = "core_acquirer_rate", key = "'core_acquirer_rate:' +  #acquirerId.toString()")
    @Override
    public List<CoreAcquirerRate> selectAcquirerRateByAcquirerId(Long acquirerId) {
        return acquirerRateMapper.selectByAcquirerId(acquirerId);
    }

    @Cacheable(value = "core_acquirer_rate", key = "'core_acquirer_rate'")
    @Override
    public List<CoreAcquirerRate> selectAllAcquirerRate() {
        return acquirerRateMapper.selectAll();
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_rate", key = "'core_acquirer_rate'", condition = "#result == true "),
            @CacheEvict(value = "core_acquirer_rate", key = "'core_acquirer_rate:' + #acquirerRate.getAcquirerId().toString()", condition = "#result == true ")
    })
    @Override
    public Boolean updateAcquirerRateById(CoreAcquirerRate acquirerRate) {
        return acquirerRateMapper.updateByPrimaryKeySelective(acquirerRate) == 1;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_rate", key = "'core_acquirer_rate'", condition = "#result == true "),
            @CacheEvict(value = "core_acquirer_rate", key = "'core_acquirer_rate:' + #acquirerRate.getAcquirerId().toString()", condition = "#result == true ")
    })
    @Override
    public Boolean addAcquirerRate(CoreAcquirerRate acquirerRate) {
        return acquirerRateMapper.insertSelective(acquirerRate) == 1;
    }

    /*
    内部调用导致AOP失效
    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_rate", allEntries = true, condition = "#result == true "),
    })*/
    @Override
    public Boolean deleteAcquirerRateByAcquirerId(Integer acquirerId) {
        return acquirerRateMapper.deleteByAcquirerId(acquirerId) > 0;
    }

    @Cacheable(value = "core_acquirer_account", key = "'core_acquirer_account'")
    @Override
    public List<CoreAcquirerAccount> selectAllAcquirerAccount() {
        return acquirerAccountMapper.selectAll();
    }

    @Override
    public List<CoreAcquirerAccount> selectAllEnableAcquirerAccount() {
        return selectAllAcquirerAccount()
                .stream()
                .filter(acquirerAccount -> acquirerAccount.getStatus().equals(SystemConstant.ENABLE))
                .collect(Collectors.toList());
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_account", key = "'core_acquirer_account'", condition = "#result == true")
    })
    @Override
    public Boolean updateAcquirerAccount(CoreAcquirerAccount acquirerAccount, String userName) {
        acquirerAccount.setModifier(userName);
        acquirerAccount.setModifyTime(new Date());
        return acquirerAccountMapper.updateByPrimaryKeySelective(acquirerAccount) == 1;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_account", key = "'core_acquirer_account'", condition = "#result == true")
    })
    @Override
    public Boolean addAcquirerAccount(CoreAcquirerAccount acquirerAccount, String userName) {
        acquirerAccount.setId(UUID.createIntegerKey(idMapper.selectLastId("core_acquirer_account")));
        acquirerAccount.setCreator(userName);
        acquirerAccount.setCreateTime(new Date());
        return acquirerAccountMapper.insertSelective(acquirerAccount) == 1;
    }

    @Caching(evict = {
            @CacheEvict(value = "core_acquirer_account", key = "'core_acquirer_account'", condition = "#result.size() != #idList.size()")
    })
    @Override
    public List<Integer> deleteAcquirerAccount(List<Integer> idList) {
        List<Integer> undeletable = new ArrayList<>();
        idList.forEach(aLong -> {
            SearchInfo searchInfo = new SearchInfo();
            searchInfo.setAcquirerAccount(aLong);
            if (orderMapper.selectCountBySearchInfo(searchInfo) == 0) {
                acquirerAccountMapper.deleteByPrimaryKey(aLong);
            } else {
                undeletable.add(aLong);
            }
        });
        return undeletable;
    }
}